package fr.generali.accueilclient.gwt.client.ui.components.form.formitem;

import java.util.Date;

import com.google.gwt.core.client.GWT;
import com.google.gwt.editor.client.EditorDelegate;
import com.google.gwt.editor.client.HasEditorDelegate;
import com.google.gwt.editor.client.LeafValueEditor;
import com.google.gwt.event.dom.client.ChangeEvent;
import com.google.gwt.event.dom.client.ChangeHandler;
import com.google.gwt.event.dom.client.HasChangeHandlers;
import com.google.gwt.event.dom.client.MouseDownEvent;
import com.google.gwt.event.dom.client.MouseDownHandler;
import com.google.gwt.event.logical.shared.ValueChangeEvent;
import com.google.gwt.event.logical.shared.ValueChangeHandler;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.i18n.client.DateTimeFormat;
import com.google.gwt.user.client.ui.HasValue;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.datepicker.client.DateBox;
import com.google.gwt.user.datepicker.client.DateBox.DefaultFormat;

import fr.generali.accueilclient.gwt.client.ui.components.form.formitem.date.DatePickerWithYearSelector;

public class DatePickerFormItem extends LabelFormItem<Date> implements HasValue<Date>, HasChangeHandlers,
                LeafValueEditor<Date>, HasEditorDelegate<Date> {

    private static final DateTimeFormat DEFAULT_FORMAT = DateTimeFormat.getFormat("dd/MM/yyyy");

    private DateBox dateBox;

    Image calendarImage;

    private EditorDelegate<Date> delegate;

    public DatePickerFormItem() {
        super(new DateBox(new DatePickerWithYearSelector(), null, (DefaultFormat ) GWT.create(DefaultFormat.class)));
        dateBox = (DateBox ) editableWidget;
        dateBox.setFormat(new DateBox.DefaultFormat(DEFAULT_FORMAT));
        addHandlerToManageImportant();
        calendarImage = new Image(res.pictoCalendrier());
        calendarImage.addStyleName(res.style().calendarImage());
        inputContainer.add(calendarImage);

        calendarImage.addMouseDownHandler(new MouseDownHandler() {

            @Override
            public void onMouseDown(MouseDownEvent event) {
                if (!dateBox.isDatePickerShowing()) {
                    dateBox.showDatePicker();
                }

            }
        });
    }

    public DateBox getDateBox() {
        return dateBox;
    }

    @Override
    protected boolean isDataFilled() {
        return dateBox.getValue() != null;
    }

    @Override
    protected void doSetValue(Date value, boolean valueIsNullOrEmpty) {
        dateBox.setValue(value);
        if (!valueIsNullOrEmpty) {
            ((Label ) readOnlyWidget).setText(DEFAULT_FORMAT.format(value));
        }
    }

    @Override
    protected boolean valueIsNullOrEmpty(Date value) {
        return value == null;
    }

    @Override
    public HandlerRegistration addValueChangeHandler(ValueChangeHandler<Date> handler) {
        return dateBox.addValueChangeHandler(handler);
    }

    @Override
    public Date getValue() {
        if (!validateMandatoryCriteria()) {
            delegate.recordError(ErrorType.MANDATORY.name(), null, null);
        }
        if (!validateDateFormat()) {
            delegate.recordError(ErrorType.INVALID_DATE.name(), null, null);
        }
        return dateBox.getValue();
    }

    public boolean validateDateFormat() {
        if (dateBox.getTextBox().getText() == null || dateBox.getTextBox().getText().isEmpty()) {
            return true;
        }
        try {
            DEFAULT_FORMAT.parse(dateBox.getTextBox().getText());
        } catch (IllegalArgumentException e) {
            return false;
        }
        return true;
    }

    @Override
    public void setValue(Date value, boolean fireEvents) {
        dateBox.setValue(value, fireEvents);
    }

    @Override
    public HandlerRegistration addChangeHandler(final ChangeHandler handler) {
        dateBox.addValueChangeHandler(new ValueChangeHandler<Date>() {

            @Override
            public void onValueChange(ValueChangeEvent<Date> event) {
                handler.onChange(null);
            }
        });
        return dateBox.getTextBox().addChangeHandler(handler);
    }

    protected void addHandlerToManageImportant() {
        ((DateBox ) editableWidget).getTextBox().addChangeHandler(new ChangeHandler() {

            @Override
            public void onChange(ChangeEvent event) {
                changeHappened();
            }

        });

        ((DateBox ) editableWidget).getTextBox().addValueChangeHandler(new ValueChangeHandler<String>() {

            @Override
            public void onValueChange(ValueChangeEvent<String> event) {
                changeHappened();
            }
        });

        ((DateBox ) editableWidget).addValueChangeHandler(new ValueChangeHandler<Date>() {

            @Override
            public void onValueChange(ValueChangeEvent<Date> event) {
                changeHappened();
            }
        });
    }

    private void changeHappened() {
        notifyUserFieldIsImportant(isImportant() && ((DateBox ) editableWidget).getTextBox().getText() == null
                        || ((DateBox ) editableWidget).getTextBox().getText().isEmpty());
    }

    @Override
    public void setDelegate(EditorDelegate<Date> delegate) {
        this.delegate = delegate;
    }

}
